package gapp.itg;

import gapp.subsysstate.ISubsysState;
import gapp.subsysstate.State;
import gapp.subsysstate.impl.SubsysState;
import gapp.utils.IObservable;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;



/**
 * A wrapper to handle the observable aspects of the stateful subsystem
 * (we should not change the subsystem to add observable facilities,
 * never change old tested code, add new code (Open closed principle))
 * 
 * NOTE: Same interface as wrapped class 
 * 
 * @author hajo
 * 
 */
public class SubsysStateObservable implements ISubsysState, IObservable {
	// Wrapped subsystem with state
	private final ISubsysState subsysState = SubsysState.newInstance();
	// Using Java beans classes to support observer pattern
	private final PropertyChangeSupport observers = new PropertyChangeSupport(
			this);

	// Singleton pattern
	private SubsysStateObservable() {
	}

	// Singleton
	private static SubsysStateObservable instance;

	// Use by service users
	public static ISubsysState getInstance() {
		if (instance == null) {
			instance = new SubsysStateObservable();
		}
		return instance;
	}

	// Used by observers
	public static IObservable getAsObservable() {
		if (instance == null) {
			instance = new SubsysStateObservable();
		}
		return instance;
	}

	// ISubsysState ----------------------
	// Never called
	@Override
	public String doService(String i) {
		try {
			return subsysState.doService(i);
		} catch (Throwable t) {
			// This should be a subsystem specific exception
			throw new IllegalStateException(t);
		}
	}

	@Override
	public State getState() {
		return subsysState.getState();
	}

	@Override
	public void setState(State s) {
		try {
			State old = subsysState.getState();
			subsysState.setState(s);
			observers.firePropertyChange(PropertyChangeNames.STATE_CHANGE
					.toString(), old, s);
		} catch (Throwable t) {
			// This should be a subsystem specific exception
			throw new IllegalStateException(t);
		}

	}

	// IObservable interface --------------------------
	@Override
	public void addPropertyChangeListener(PropertyChangeListener observer) {
		observers.addPropertyChangeListener(observer);
	}

	@Override
	public void removePropertyChangeListener(PropertyChangeListener observer) {
		observers.removePropertyChangeListener(observer);

	}
}
